/*
 * my_cli_pro.c
 *
 *  Created on: Aug 31, 2009
 *      Author: lius
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "my_plugin.h"
#include "my_debug.h"
#include "mail_file_opt.h"

epoll_cntl_func my_ser_cntl;
epoll_recv_func my_ser_recv;
epoll_send_func my_ser_send;
void *pbase = NULL;

char *mail_data_buf = NULL;
int mail_data_len = 0;

typedef struct _link_info{
	int offset;
	int status;
} link_info_t;

link_info_t link_info[65535] = {};

#define INDEX(handle) ((handle / 10000)*10000 + (handle % 10000))

enum {
	POP_SERVER_BANNER = 0,
	POP_SERVER_USER,
	POP_SERVER_PASS,
	POP_SERVER_LIST,
	POP_SERVER_UIDL,
	POP_SERVER_STAT,
	POP_SERVER_RETR,
	POP_SERVER_RETR_MAIL,
	POP_SERVER_MAIL_END,
	POP_SERVER_QUIT
};

char globle_data_buf[][255] = { "+OK Server ready\r\n",
								"+OK user    succ\r\n",
								"+OK pass    succ\r\n",
								"+OK list    succ\r\n1 1024\r\n.\r\n",
								"+OK uidl    succ\r\n1 abcd\r\n.\r\n",
								"+OK 1 1024      \r\n",
								"+OK retr    succ\r\n",
								"",
								"\r\n.\r\n",
								"+OK quit    succ\r\n",
								};


inline void pop_stat_turn(link_info_t *pinfo, int cli_stat, int offset)
{
	pinfo->status = cli_stat + 1 > POP_SERVER_QUIT ? POP_SERVER_BANNER : cli_stat + 1;
	pinfo->offset = offset;
	DEBUG_EPOLL(EPOLL_DBG_STAT, EPOLL_DEBUG, "status=[%d];offset=[%d]\n", pinfo->status, pinfo->offset);
}


int my_ser_init(base_func_t *pfunc)
{
	void *pf = NULL;
	long mail_size = 0;
	FUNC_START("pfunc = [%p]\n", pfunc);

	my_ser_cntl = pfunc->epoll_cntl;
	my_ser_recv = pfunc->epoll_recv;
	my_ser_send = pfunc->epoll_send;
	pbase = pfunc->pepoll;

	pf = mail_open_file(pfunc->pfile);
	if(pf == NULL)
	{
		FUNC_RETURN(-1);
	}
	mail_size = mail_get_file_size(pf);
	if(mail_size <= 0)
	{
		FUNC_RETURN(-2);
	}
	else
	{
		mail_data_len = mail_size;
		mail_data_buf = calloc(1, mail_size + 1);
		if(NULL == mail_data_buf)
		{
			DEBUG_EPOLL(EPOLL_DBG_STAT, EPOLL_ERROR, "[%s]calloc mail file size[%d] fail\n", pfunc->pfile, mail_data_len + 1);
			FUNC_RETURN(-4);
		}
	}
	if(mail_read_file(pf, 0, mail_size, mail_data_buf) != mail_size)
	{
		FUNC_RETURN(-3);
	}
	mail_close_file(pf);
	FUNC_RETURN(0);
}

int my_ser_exit(void)
{
	FUNC_START("\n");
	FUNC_RETURN(0);
}


int my_ser_write(int handle)
{
	link_info_t *pinfo = &link_info[INDEX(handle)];
	char *data_buf = NULL;
	int  buf_len = 0;
	int ret = 0;
	int send_len = 0;
	FUNC_START("handle = [%d]\n", handle);
	do{
		DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_DEBUG, "send data offset=[%d]\n", pinfo->offset);
		if(pinfo->status == POP_SERVER_RETR_MAIL)
		{
			data_buf = mail_data_buf + pinfo->offset;
			buf_len = mail_data_len - pinfo->offset;
			send_len = buf_len > 1024 *10 ? 1024 *10 : buf_len;
		}
		else
		{
			data_buf = (char *)globle_data_buf[pinfo->status] + pinfo->offset;
			buf_len = send_len = strlen(data_buf);
		}
		DEBUG_EPOLL(EPOLL_DBG_DATA, EPOLL_DEBUG, "before send data=[%.*s]\n", send_len, data_buf);
		ret = my_ser_send(handle, data_buf, send_len);
		DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_DEBUG, "send ret=[%d]\n", ret);
		if(ret < buf_len && ret >= 0)
		{
			 DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_DEBUG, "send ret=[%d]\n", ret);
			 my_ser_cntl(pbase, handle, EPOLL_OP_MODIFY, EPOLL_EV_WRITE);
			 pop_stat_turn(pinfo, pinfo->status - 1, pinfo->offset + ret);
			 FUNC_RETURN(ret);
		}
		else if(ret < 0)
		{
			//my_ser_cntl(pbase, handle, EPOLL_OP_CLOSE, EPOLL_EV_RANDW);
			FUNC_RETURN(ret);
		}
		else
		{
			pop_stat_turn(pinfo, pinfo->status, 0);
			my_ser_cntl(pbase, handle, EPOLL_OP_MODIFY, EPOLL_EV_READ);
		}
	}while(pinfo->status == POP_SERVER_RETR_MAIL ||
			pinfo->status == POP_SERVER_MAIL_END);
	FUNC_RETURN(ret);
}

int my_ser_start(int handle)
{
	int ret = 0;
	link_info_t *pinfo = &link_info[INDEX(handle)];
	FUNC_START("handle = [%d]\n", handle);
	pinfo->status = POP_SERVER_BANNER;
	pinfo->offset = 0;
	//my_ser_cntl(pbase, handle, EPOLL_OP_CLOSE, EPOLL_EV_RANDW);
	//FUNC_RETURN(0);
	ret = my_ser_write(handle);
	FUNC_RETURN(ret);
}

int my_ser_read(int handle)
{
	char data_buf[1024];
	link_info_t *pinfo = &link_info[INDEX(handle)];
	int ret = 0;

	FUNC_START("handle = [%d]\n", handle);

	memset(data_buf, 0x00, sizeof(data_buf));
	ret = my_ser_recv(handle, data_buf, sizeof(data_buf) - 1);
	DEBUG_EPOLL(EPOLL_DBG_DATA, EPOLL_DEBUG, "recv data=[%.*s]\n", ret, data_buf);
	if(ret > 0)
	{
		if(data_buf[ret - 2] == '\r' && data_buf[ret - 1] == '\n')
		{

			if(strncasecmp(data_buf, "quit", 4) == 0)
			{
				pop_stat_turn(pinfo, POP_SERVER_QUIT - 1, 0);
				my_ser_write(handle);
				//my_ser_cntl(pbase, handle, EPOLL_OP_CLOSE, EPOLL_EV_RANDW);
				ret = 0;
			}
			else
			{
				my_ser_write(handle);
			}
		}
		//FUNC_RETURN(ret);
	}
//	else
//	{
//		my_ser_cntl(pbase, handle, EPOLL_OP_CLOSE, EPOLL_EV_RANDW);
	FUNC_RETURN(ret);
//	}
}

int my_ser_end(int handle)
{
	FUNC_START("handle = [%d]\n", handle);
	my_ser_cntl(pbase, handle, EPOLL_OP_CLOSE, EPOLL_EV_RANDW);
	FUNC_RETURN(0);
}

